/* SPDX-License-Identifier: GPL-2.0 */
#ifndef SEMINIX_STRING_H
#define SEMINIX_STRING_H

#include <seminix/types.h>	/* for usize */
#include <seminix/stdarg.h>

/*
 * Include machine specific inline routines
 */
#include <asm/string.h>

#ifndef __HAVE_ARCH_STRCPY
extern char * strcpy(char *,const char *);
#endif
#ifndef __HAVE_ARCH_STRNCPY
extern char * strncpy(char *,const char *, usize);
#endif
#ifndef __HAVE_ARCH_STRLCPY
usize strlcpy(char *, const char *, usize);
#endif
#ifndef __HAVE_ARCH_STRSCPY
isize strscpy(char *, const char *, usize);
#endif
#ifndef __HAVE_ARCH_STRCAT
extern char * strcat(char *, const char *);
#endif
#ifndef __HAVE_ARCH_STRNCAT
extern char * strncat(char *, const char *, usize);
#endif
#ifndef __HAVE_ARCH_STRLCAT
extern usize strlcat(char *, const char *, usize);
#endif
#ifndef __HAVE_ARCH_STRCMP
extern int strcmp(const char *,const char *);
#endif
#ifndef __HAVE_ARCH_STRNCMP
extern int strncmp(const char *,const char *,usize);
#endif
#ifndef __HAVE_ARCH_STRCASECMP
extern int strcasecmp(const char *s1, const char *s2);
#endif
#ifndef __HAVE_ARCH_STRNCASECMP
extern int strncasecmp(const char *s1, const char *s2, usize n);
#endif
#ifndef __HAVE_ARCH_STRCHR
extern char * strchr(const char *,int);
#endif
#ifndef __HAVE_ARCH_STRCHRNUL
extern char * strchrnul(const char *,int);
#endif
#ifndef __HAVE_ARCH_STRNCHR
extern char * strnchr(const char *, usize, int);
#endif
#ifndef __HAVE_ARCH_STRRCHR
extern char * strrchr(const char *,int);
#endif

#ifndef __HAVE_ARCH_STRSTR
extern char * strstr(const char *, const char *);
#endif
#ifndef __HAVE_ARCH_STRNSTR
extern char * strnstr(const char *, const char *, usize);
#endif
#ifndef __HAVE_ARCH_STRLEN
extern usize strlen(const char *);
#endif
#ifndef __HAVE_ARCH_STRNLEN
extern usize strnlen(const char *,usize);
#endif
#ifndef __HAVE_ARCH_STRPBRK
extern char * strpbrk(const char *,const char *);
#endif
#ifndef __HAVE_ARCH_STRSEP
extern char * strsep(char **,const char *);
#endif
#ifndef __HAVE_ARCH_STRSPN
extern usize strspn(const char *,const char *);
#endif
#ifndef __HAVE_ARCH_STRCSPN
extern usize strcspn(const char *,const char *);
#endif

#ifndef __HAVE_ARCH_MEMSET
extern void * memset(void *,int,usize);
#endif

#ifndef __HAVE_ARCH_MEMSET16
extern void *memset16(u16 *, u16, usize);
#endif

#ifndef __HAVE_ARCH_MEMSET32
extern void *memset32(u32 *, u32, usize);
#endif

#ifndef __HAVE_ARCH_MEMSET64
extern void *memset64(u64 *, u64, usize);
#endif

static inline void *memset_l(unsigned long *p, unsigned long v,
        usize n)
{
    if (BITS_PER_LONG == 32)
        return memset32((u32 *)p, v, n);
    else
        return memset64((u64 *)p, v, n);
}

static inline void *memset_p(void **p, void *v, usize n)
{
    if (BITS_PER_LONG == 32)
        return memset32((u32 *)p, (uintptr_t)v, n);
    else
        return memset64((u64 *)p, (uintptr_t)v, n);
}

extern void **__memcat_p(void **a, void **b);
#define memcat_p(a, b) ({					\
    BUILD_BUG_ON_MSG(!__same_type(*(a), *(b)),		\
             "type mismatch in memcat_p()");	\
    (typeof(*a) *)__memcat_p((void **)(a), (void **)(b));	\
})

#ifndef __HAVE_ARCH_MEMCPY
extern void * memcpy(void *,const void *,usize);
#endif
#ifndef __HAVE_ARCH_MEMMOVE
extern void * memmove(void *,const void *,usize);
#endif
#ifndef __HAVE_ARCH_MEMSCAN
extern void * memscan(void *,int,usize);
#endif
#ifndef __HAVE_ARCH_MEMCMP
extern int memcmp(const void *,const void *,usize);
#endif
#ifndef __HAVE_ARCH_MEMCHR
extern void * memchr(const void *,int,usize);
#endif
#ifndef __HAVE_ARCH_MEMCPY_MCSAFE
static inline unsigned long memcpy_mcsafe(void *dst,
        const void *src, usize cnt)
{
    memcpy(dst, src, cnt);
    return 0;
}
#endif
#ifndef __HAVE_ARCH_MEMCPY_FLUSHCACHE
static inline void memcpy_flushcache(void *dst, const void *src, usize cnt)
{
    memcpy(dst, src, cnt);
}
#endif

extern __printf(2, 3) int sprintf(char *buf, const char * fmt, ...);
extern __printf(2, 0) int vsprintf(char *buf, const char *, va_list);

extern __printf(3, 4)
int snprintf(char *buf, usize size, const char *fmt, ...);
extern __printf(3, 0)
int vsnprintf(char *buf, usize size, const char *fmt, va_list args);

extern __printf(3, 0) int vscnprintf(char *buf, usize size, const char *fmt, va_list args);
extern __printf(3, 4) int scnprintf(char *buf, usize size, const char *fmt, ...);

extern __printf(2, 3) __malloc char *kasprintf(gfp_t gfp, const char *fmt, ...);
extern __printf(2, 0) __malloc char *kvasprintf(gfp_t gfp, const char *fmt, va_list args);
extern char *kstrdup(const char *s, gfp_t gfp) __malloc;
extern const char *kstrdup_const(const char *s, gfp_t gfp);

extern void kfree_const(const void *x);

#endif /* !SEMINIX_STRING_H */
